﻿using iDetector;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using static iDetector.SdkInterface;

namespace DART.Detector.IRay.Wrapper
{
    public class IRayException : Exception
    {
        public IRayException(int error)
            : base(error.GetMessage())
        {
            Error = error;
        }

        public IRayException(int error, IRayCmd cmd)
            : base($"{error.GetMessage()}, Cmd:{cmd}")
        {
            Error = error;
        }

        public IRayException(IRayEventArgs args)
            : base($"{((int)args.Param2).GetMessage()}, Cmd:{args.Param1}, Evt:{args.EventID}, Err:{args.Param2}")
        {
            Error = (int)args.Param2;
        }

        public int Error { get; protected set; }
    }

    internal static partial class IRayExtensions
    {
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        [DebuggerStepThrough]
        public static IRayError ThrowIfError(this int error)
        {
            if (error != (int)IRayError.OK)
            {
                throw new IRayException(error);
            }
            return (IRayError)error;
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        [DebuggerStepThrough]
        public static void TrySetExceptionIfError<T>(this TaskCompletionSource<T> tcs, int error)
        {
            if (error != (int)IRayError.OK)
                tcs.TrySetException(new IRayException(error));
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        [DebuggerStepThrough]
        public static string GetMessage(this int error)
        {
            return string.Join(",", error.GetErrorInfo());
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        [DebuggerStepThrough]
        public static IEnumerable<string> GetErrorInfo(this int error)
        {
            ErrorInfo info = new ErrorInfo();
            GetErrInfo(error, ref info);
            return new[] { info.strDescription.Trim('\"'), info.strSolution.Trim('\"') }.Where(_ => !string.IsNullOrWhiteSpace(_));
        }
    }
}